package com.abel.bigwater.data.sanchuan

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.data.mapper.DataMapper
import com.abel.bigwater.data.mapper.RtuMapper
import com.alibaba.fastjson.JSON
import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.channel.socket.DatagramPacket
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
import java.net.InetSocketAddress

@SpringBootTest
@RunWith(SpringRunner::class)
class SanchuanDecoderTests {

    @Value("\${yujiang.firmId}")
    var firmIdYu: String? = null

    @Value("\${yujiang.firmCode}")
    var firmCodeYu: String? = null

    @Autowired
    var rtuMapper: RtuMapper? = null

    @Autowired
    var dataMapper: DataMapper? = null

    @Test
    fun testOnlineEmpty() {
        val msg = """68 00 4e 68 11 00 10 11 02 03 04 05 36 01 20 18 06 01 02 03 00 16 a4 19 64 00 03 00 03 2b 00 00
19 fc 1b fc 08 03 00 ff 7f 34 12 56 10 11 02 03 04 05 36 01 bc cc 5b 07 00 08 0a 0c 00 00 00 00
00 02 00 13 18 05 06 07 08 00 00 24 90 00 00 16 07 08 02 16"""

        val ch = EmbeddedChannel(object : SanchuanDecoder() {
            override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
                super.decode(ctx, `in`, out)
                lgr.info("decoder parsed:\n${JSON.toJSONString(out, true)}")
                assert(1 == out!!.size)
            }
        })

        val buf = Unpooled.buffer().writeBytes(BcdString.fromBcdString(msg, false).hexArray)
        ch.writeInbound(buf)

        val t = GlobalScope.async { Thread.sleep(2000) }
        runBlocking { t.await() }
    }

    @Test
    fun testOnlineEmptyBla() {
        val msg1 = """68 00 4e 68 11 00 10 11 02 03 04 05 36 01 20 18 06 01 02 03 00 16 a4 19 64 00 03 00 03 2b 00 00
19 fc 1b fc 08 03 00 ff 7f 34 12 56 10 11 02 03 04 05 36 01 bc cc 5b 07 00 08 0a 0c 00 00 00 00
00 02 00 13 18 05 06 07 08 00 00 24 90 00 00 16 07 08 02 16 68 00 4e 68"""
        val msg2 = """11 00 10 11 02 03 04 05 36 01 20 18 06 01 02 03 00 16 a4 19 64 00 03 00 03 2b 00 00
19 fc 1b fc 08 03 00 ff 7f 34 12 56 10 11 02 03 04 05 36 01 bc cc 5b 07 00 08 0a 0c 00 00 00 00
00 02 00 13 18 05 06 07 08 00 00 24 90 00 00 16 07 08 02 16"""

        var cnt = 0

        val ch = EmbeddedChannel(object : SanchuanDecoder() {
            override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
                super.decode(ctx, `in`, out)
                lgr.info("decoder parsed:\n${JSON.toJSONString(out, true)}")

                cnt += out?.size ?: 0
            }
        })

        val buf = Unpooled.buffer().writeBytes(BcdString.fromBcdString(msg1).hexArray)
        ch.writeInbound(buf)
        val buf2 = buf.alloc().buffer().writeBytes(BcdString.fromBcdString(msg2).hexArray)
        ch.writeInbound(buf2)

        val t = GlobalScope.async { Thread.sleep(2000) }
        runBlocking { t.await() }

        // 收到2个完整消息包
        assert(2 == cnt)
    }

    @Test
    fun testOnlinePersist() {
        val msg = """68 00 4e 68 11 00 10 11 02 03 04 05 36 01 20 18 06 01 02 03 00 16 a4 19 64 00 03 00 03 2b 00 00
19 fc 1b fc 08 03 00 ff 7f 34 12 56 10 11 02 03 04 05 36 01 bc cc 5b 07 00 08 0a 0c 00 00 00 00
00 02 00 13 18 05 06 07 08 00 00 24 90 00 00 16 07 08 02 16"""

        val ch = EmbeddedChannel(object : SanchuanDecoder() {
            override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
                super.decode(ctx, `in`, out)
                lgr.info("decoder parsed:\n${JSON.toJSONString(out, true)}")
                assert(1 == out!!.size)
            }
        }, SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmIdYu!!, firmCodeYu!!))

        val buf = Unpooled.buffer().writeBytes(BcdString.fromBcdString(msg, false).hexArray)
        ch.writeInbound(buf)

        val t = GlobalScope.async { Thread.sleep(2000) }
        runBlocking { t.await() }
    }

    @Test
    fun testOnlineUdp() {
        val msg = """68 00 4e 68 11 00 10 11 02 03 04 05 36 01 20 18 06 01 02 03 00 16 a4 19 64 00 03 00 03 2b 00 00
19 fc 1b fc 08 03 00 ff 7f 34 12 56 10 11 02 03 04 05 36 01 bc cc 5b 07 00 08 0a 0c 00 00 00 00
00 02 00 13 18 05 06 07 08 00 00 24 90 00 00 16 07 08 02 16"""

        val ch = EmbeddedChannel(object : SanchuanDecoder() {
            override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
                super.decode(ctx, `in`, out)
                lgr.info("decoder parsed:\n${JSON.toJSONString(out, true)}")
                assert(1 == out!!.size)
            }
        }, SanchuanUdpHandler(dataMapper!!, rtuMapper!!, firmIdYu!!, firmCodeYu!!))

        val pkt = DatagramPacket(Unpooled.buffer().writeBytes(BcdString.toByteArray(msg)), InetSocketAddress(9237))
        ch.writeInbound(pkt)

        val t = GlobalScope.async { Thread.sleep(2000) }
        runBlocking { t.await() }
    }

    companion object {
        private val lgr = LoggerFactory.getLogger(SanchuanDecoderTests::class.java)
    }
}